import router from "@/router";
import { REPORT_EVENT_TYPE, useReportEvent } from "@/hooks";
import { useAccountStore } from "@/store";

/**
 * @description 请求配置
 */
const BASE_URL = "/api";
const TIMEOUT = 10000;

/**
 * @description 请求成功回调函数类型定义
 * @param response 响应数据，包含状态码、业务数据和消息
 * @param result uni.request 成功回调的原始结果对象
 */
export type OnSuccessType = (
    response: ResponseData<string | AnyObject | ArrayBuffer>,
    result: UniNamespace.RequestSuccessCallbackResult
) => void;

/**
 * @description 请求失败回调函数类型定义
 * @param error uni.request 失败回调的错误对象
 */
export type OnErrorType = (error: UniNamespace.GeneralCallbackResult) => void;

/**
 * @description 请求完成回调函数类型定义（无论成功或失败都会执行）
 * @param error uni.request 完成回调的错误对象
 */
export type OnCompleteType = (error: UniNamespace.GeneralCallbackResult) => void;

/**
 * @description 请求配置接口定义
 */
interface RequestConfig {
    /** 请求地址 */
    url: string;
    /** 请求方法，默认为 GET */
    method?: "GET" | "POST" | "PUT" | "DELETE";
    /** 请求参数数据 */
    data?: string | AnyObject;
    /** 请求头信息 */
    header?: Record<string, string>;
    /** 超时时间（毫秒），默认为 10000 */
    timeout?: number;
    /** 是否显示加载提示，默认为 true */
    loading?: boolean;
    /** 是否需要认证鉴权，默认为 true */
    auth?: boolean;
}

/**
 * @description 后端响应数据结构定义
 * @template T 泛型，表示响应数据的具体类型
 */
interface ResponseData<T> {
    /** 状态码 */
    code: number;
    /** 实际业务数据 */
    data: T | any | null;
    /** 响应消息 */
    message: string;
}

/**
 * @description 通用请求函数类型定义
 * @param options 请求配置项
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
type RequestFnType = (
    options: RequestConfig,
    onSuccess?: OnSuccessType,
    onError?: OnErrorType,
    onComplete?: OnCompleteType
) => UniNamespace.RequestTask;

/**
 * @description 简化版请求函数类型定义（将 url 和 data 提取为独立参数）
 * @param url 请求地址
 * @param data 请求参数数据
 * @param options 其他请求配置项（不包括 url、method 和 data）
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
type CommonRequestFnType = (
    url: string,
    data?: string | AnyObject | ArrayBuffer,
    options?: Omit<RequestConfig, "url" | "method" | "data">,
    onSuccess?: OnSuccessType,
    onError?: OnErrorType,
    onComplete?: OnCompleteType
) => UniNamespace.RequestTask;

/**
 * @description HTTP 错误码处理函数
 * @param statusCode HTTP 状态码
 * @param config
 */
const handleHttpError = (statusCode: number, config: UniNamespace.RequestOptions) => {
    const errorMap: Record<number, string> = {
        400: "请求错误",
        401: "未授权，请重新登录",
        403: "拒绝访问",
        404: "请求地址出错",
        408: "请求超时",
        500: "服务器内部错误",
        501: "服务未实现",
        502: "网关错误",
        503: "服务不可用",
        504: "网关超时",
        505: "HTTP版本不受支持"
    };

    const message = errorMap[statusCode] || "未知错误";

    // 特殊处理 401 未授权错误：清除本地 token 并跳转到登录页
    if (statusCode === 401) {
        uni.removeStorageSync("token");
        setTimeout(() => {
            uni.navigateTo({
                url: router.PATH.__PACKAGE_LOGIN
            });
        }, 1500);
    }

    useReportEvent(REPORT_EVENT_TYPE.REQUEST_ERROR, {
        statusCode,
        statusCodeOfMessage: message,
        timestamp: Date.now(),
        config
    });
};

/**
 * @description 核心网络请求方法
 * @param options 请求配置项
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
const request: RequestFnType = (options, onSuccess, onError, onComplete) => {
    const { url, ...restOptions } = options;
    const accountStore = useAccountStore();

    const config: UniNamespace.RequestOptions = {
        url: import.meta.env.TTS_HTTP_API_URL + BASE_URL + url,
        method: options.method || "GET",
        data: options.data,
        header: {
            token: accountStore.token,
            ["Content-Type"]: "application/json",
            ...options.header
        },
        timeout: TIMEOUT,
        ...restOptions
    };

    // 若需要认证，则自动添加 Authorization 请求头
    if (options.auth !== false) {
        const token = uni.getStorageSync("token");
        if (token) {
            config.header = {
                ...config.header,
                Authorization: `Bearer ${token}`
            };
        }
    }

    return uni.request({
        ...config,
        success: (result: UniNamespace.RequestSuccessCallbackResult) => {
            const { statusCode, data } = result;

            // 判断是否为成功的 HTTP 状态码
            if ((statusCode >= 200 && statusCode < 300) || statusCode === 304) {
                onSuccess && onSuccess(data as ResponseData<string | AnyObject>, result);
            } else {
                handleHttpError(statusCode, config);
                onError &&
                    onError({ errMsg: "HTTP Error", statusCode: statusCode } as UniNamespace.GeneralCallbackResult);
            }
        },
        fail: (error: UniNamespace.GeneralCallbackResult) => {
            onError && onError(error);
        },
        complete: (error: UniNamespace.GeneralCallbackResult) => {
            onComplete && onComplete(error);
        }
    });
};

/**
 * @description GET 请求方法封装
 * @param url 请求地址
 * @param data 请求参数数据
 * @param options 其他请求配置项
 * @param onSuccess 请求成功的回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
const GET: CommonRequestFnType = (url, data, options, onSuccess, onError, onComplete) => {
    return request(
        {
            url,
            method: "GET",
            data,
            ...options
        },
        onSuccess,
        onError,
        onComplete
    );
};

/**
 * @description POST 请求方法封装
 * @param url 请求地址
 * @param data 请求参数数据
 * @param options 其他请求配置项
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
const POST: CommonRequestFnType = (url, data, options, onSuccess, onError, onComplete) => {
    return request(
        {
            url,
            method: "POST",
            data,
            ...options
        },
        onSuccess,
        onError,
        onComplete
    );
};

/**
 * @description PUT 请求方法封装
 * @param url 请求地址
 * @param data 请求参数数据
 * @param options 其他请求配置项
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
const PUT: CommonRequestFnType = (url, data, options, onSuccess, onError, onComplete) => {
    return request(
        {
            url,
            method: "PUT",
            data,
            ...options
        },
        onSuccess,
        onError,
        onComplete
    );
};

/**
 * @description DELETE 请求方法封装
 * @param url 请求地址
 * @param data 请求参数数据
 * @param options 其他请求配置项
 * @param onSuccess 请求成功地回调函数
 * @param onError 请求失败的回调函数
 * @param onComplete 请求完成的回调函数
 * @returns uni.request 返回的任务对象
 */
const DELETE: CommonRequestFnType = (url, data, options, onSuccess, onError, onComplete) => {
    return request(
        {
            url,
            method: "DELETE",
            data,
            ...options
        },
        onSuccess,
        onError,
        onComplete
    );
};

export { request, GET, POST, PUT, DELETE, type RequestConfig, type ResponseData };
